[코담]
웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트
전체 흐름 Part6 | ✅저자: 이유정(박사)
Tutorial 6: ViewSets & Routers에서는 기존의 뷰 클래스들을 ViewSet
으로 통합하고, URL 구성을 DefaultRouter
로 자동화하는 방식으로 변경되었습니다.
UserViewSet
, SnippetViewSet
추가 / 기존 뷰들 제거 (SnippetList
, SnippetDetail
, SnippetHighlight
, UserList
, UserDetail
, api_root
)
snippets/views.py
from rest_framework import viewsets, permissions, renderers
from rest_framework.decorators import action
from rest_framework.response import Response
from django.contrib.auth.models import User
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from snippets.permissions import IsOwnerOrReadOnly
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
🔹 UserViewSet
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
- 용도: 사용자 목록과 단일 사용자 정보를 읽기 전용(ReadOnly) 으로 제공
ReadOnlyModelViewSet
은list()
와retrieve()
만 제공하므로 사용자 생성/수정은 불가
🔹 SnippetViewSet
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
- 용도: 코드 스니펫에 대해 CRUD API 제공
ModelViewSet
은list
,create
,retrieve
,update
,destroy
등을 자동 지원permission_classes
는:- 인증된 사용자만 쓰기 가능 (
IsAuthenticatedOrReadOnly
) - 오직 소유자만 수정/삭제 가능 (
IsOwnerOrReadOnly
: 커스텀 권한)
- 인증된 사용자만 쓰기 가능 (
🔹 커스텀 액션: highlight
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
- 기능: 특정 스니펫을 HTML 형식으로 하이라이트된 상태로 반환
- URL 예:
/snippets/1/highlight/
StaticHTMLRenderer
덕분에 HTML 응답을 반환함 (e.g., 하이라이트된 코드)
🔹 객체 생성 시 소유자 자동 지정
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
기능: POST
요청으로 스니펫을 생성할 때 현재 요청한 유저를 owner
로 자동 설정
📌 관련 커스텀 권한 클래스 예시 (IsOwnerOrReadOnly
)
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.owner == request.user
용도: 읽기는 모두 허용, 수정/삭제는 객체의 소유자만 허용
✅ 전체 흐름 요약
/users/
: 사용자 정보 조회/snippets/
: 코드 스니펫 CRUD/snippets/{id}/highlight/
: 특정 스니펫의 HTML 하이라이트 보기- 인증 없이 읽기는 가능, 쓰기는 인증 필요
- 객체 소유자만 수정/삭제 가능
기존 뷰 분기 방식 제거 → Router 기반 URL 자동 구성으로 변경
snippets/urls.py
from snippets import views
from django.urls import path, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet, basename='snippet')
router.register(r'users', views.UserViewSet, basename='user')
urlpatterns = [
path('', include(router.urls)),
]
기존에 수동으로 정의했던 path('snippets/...')
, path('users/...')
, api_root
등은 모두 제거됨
[test]
http://127.0.0.1:8000/snippets/
http://127.0.0.1:8000/snippets/1/
http://127.0.0.1:8000/users/
http://127.0.0.1:8000/users/1/
http://127.0.0.1:8000/
http://127.0.0.1:8000/snippets/1/highlight/